package com.valuegroup.smarttodo.data.service;

import android.text.TextUtils;

import com.alibaba.fastjson.JSON;
import com.valuegroup.smarttodo.data.ServiceFactory;
import com.valuegroup.smarttodo.data.enums.TaskSortTypeEnum;
import com.valuegroup.smarttodo.data.model.AppStatus;
import com.valuegroup.smarttodo.data.model.Curriculum;
import com.valuegroup.smarttodo.data.model.Event;
import com.valuegroup.smarttodo.data.model.Goals;
import com.valuegroup.smarttodo.data.model.Habit;
import com.valuegroup.smarttodo.data.model.Task;
import com.valuegroup.smarttodo.data.model.TaskDao;
import com.valuegroup.smarttodo.data.model.TaskStep;
import com.valuegroup.smarttodo.data.model.TaskStepDao;
import com.valuegroup.smarttodo.data.vo.CalendarQueryParams;
import com.valuegroup.smarttodo.data.vo.KeyValueVo;
import com.valuegroup.smarttodo.data.vo.TaskItemVo;
import com.valuegroup.smarttodo.data.vo.TaskStepVo;
import com.valuegroup.smarttodo.plugins.pickdialog.DateUtils;
import com.valuegroup.smarttodo.util.CollectionUtils;

import org.greenrobot.greendao.query.QueryBuilder;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import androidx.annotation.NonNull;


public class TaskService extends BaseService {


    public List<TaskItemVo> findTaskForHome(boolean hideFinish, TaskSortTypeEnum sortType, boolean isDesc) {
        List<TaskItemVo> result = new ArrayList<>();

        List<Task> data = new ArrayList<>();

        // 查询截止日期小于当前日期的未完成任务
        data.addAll(findUnFinishAndBeforeDayTask());
        // 查询查询截止日期等于今天的任务
        data.addAll(findDayTask());

        // 对结果集排序处理
        Collections.sort(data, getComparatorBySortType(TaskSortTypeEnum.DEADLINE, false));
        Collections.sort(data, getComparatorBySortType(sortType, isDesc));

        for (Task t : data) {
            TaskItemVo vo = convertTask(t);
            if (hideFinish) {
                if (!vo.isShowFinish()) {
                    result.add(vo);
                }
            } else {
                result.add(vo);
            }
        }

        return result;
    }

    private Comparator<Task> getComparatorBySortType(TaskSortTypeEnum sortType, boolean isDesc) {
        if (isDesc) {
            switch (sortType) {
                case DEADLINE:
                    return new DeadlineDescComparetor();
                case FINISH:
                    return new FinishDescComparetor();
                case ABC:
                    return new TitleDescComparetor();
                case CREATEDDT:
                    return new CreateDtDescComparetor();
                case UPDATEDT:
                    return new UpdateDtDescComparetor();
                case QUADRANT:
                    return new QuadrantDescComparetor();
                default:
                    return new QuadrantDescComparetor();
            }
        } else {
            switch (sortType) {
                case DEADLINE:
                    return new DeadlineAscComparetor();
                case FINISH:
                    return new FinishAscComparetor();
                case ABC:
                    return new TitleAscComparetor();
                case CREATEDDT:
                    return new CreateDtAscComparetor();
                case UPDATEDT:
                    return new UpdateDtAscComparetor();
                case QUADRANT:
                    return new QuadrantAscComparetor();
                default:
                    return new QuadrantAscComparetor();
            }
        }
    }


    public List<TaskItemVo> findTaskForOrder(CalendarQueryParams p) {
        List<TaskItemVo> result = new ArrayList<>();

        List<Task> data = new ArrayList<>();

        if (!TextUtils.isEmpty(p.getSearchKey())) {
            // 查询关键字（查询所有）
            data.addAll(searchTask(p.getSearchKey()));
        } else {
            // 按截止日期查询(0 全部；1已完成；2未完成)
            if (p.getFilterType() == 2) {
                data.addAll(findDayTask(p.getFindDay(), false, true));
            } else if (p.getFilterType() == 1) {
                data.addAll(findDayTask(p.getFindDay(), true, false));
            } else {
                data.addAll(findDayTask(p.getFindDay(), false, false));
            }
        }

        for (Task t : data) {
            result.add(convertTask(t));
        }

        return result;
    }

    public List<Task> searchTask(String searchKey) {
        QueryBuilder<Task> q = getTaskDao().queryBuilder();
        if (!TextUtils.isEmpty(searchKey)) {
            q.where(TaskDao.Properties.Title.like("%" + searchKey + "%"));
        }
        q.where(TaskDao.Properties.Status.eq(AppStatus.Status.NORMAL));
        return q.list();
    }

    // 查询截止日期小于当前日期的未完成任务
    public List<Task> findUnFinishAndBeforeDayTask() {
        QueryBuilder<Task> q = getTaskDao().queryBuilder();
        q.where(TaskDao.Properties.IsFinish.eq(false));
        // < 2019-01-10 00:00:00
        q.where(TaskDao.Properties.Deadline.lt(DateUtils.setStartTime()));
        q.where(TaskDao.Properties.Status.eq(AppStatus.Status.NORMAL));
        return q.list();
    }

    // 查询查询截止日期等于今天的任务
    public List<Task> findDayTask() {
        QueryBuilder<Task> q = getTaskDao().queryBuilder();
        // <= 2019-01-10 23:59:59
        q.where(TaskDao.Properties.Deadline.le(DateUtils.setEndTime()));
        // >= 2019-01-10 00:00:00
        q.where(TaskDao.Properties.Deadline.ge(DateUtils.setStartTime()));
        q.where(TaskDao.Properties.Status.eq(AppStatus.Status.NORMAL));
        return q.list();
    }

    public List<Task> findDayTask(Date findDay, boolean onlyFinish, boolean onlyUnFinish) {
        QueryBuilder<Task> q = getTaskDao().queryBuilder();
        // <= 2019-01-10 23:59:59
        q.where(TaskDao.Properties.Deadline.le(DateUtils.setEndTime(findDay)));
        // >= 2019-01-10 00:00:00
        q.where(TaskDao.Properties.Deadline.ge(DateUtils.setStartTime(findDay)));
        if (onlyFinish) {
            q.where(TaskDao.Properties.IsFinish.eq(true));
        }
        if (onlyUnFinish) {
            q.where(TaskDao.Properties.IsFinish.eq(false));
        }
        q.where(TaskDao.Properties.Status.eq(AppStatus.Status.NORMAL));
        return q.list();
    }

    public List<TaskStepVo> findTaskStepForDetail(Long id) {
        List<TaskStepVo> result = new ArrayList<>();
        for (TaskStep t : findTaskStep(id)) {
            result.add(TaskStepVo.convertTaskStep(t));
        }
        return result;
    }

    public TaskItemVo addTaskForFast(String title, int preMinute) {

        Task t = getDefaultTaskData();
        t.setTitle(title);
        t.setPreMinute(preMinute);
        getTaskDao().save(t);
        getTaskDao().detachAll();

        return convertTask(t);
    }

    public TaskStepVo addTaskStep(TaskStepVo vo) {
        if (vo.getTaskId() == null) {
            return null;
        }

        TaskStep t = getDefaultTaskStepData(vo.getTaskId());
        t.setTitle(vo.getTitle());
        t.setSort(vo.getSort());
        getTaskStepDao().save(t);

        System.out.println("新增任务：" + JSON.toJSON(t));
        return TaskStepVo.convertTaskStep(t);
    }


    public void delTask(Long id) {
        Task t = load(id);
        if (t == null) {
            return;
        }

        List<TaskStep> steps = findTaskStep(id);
        if (CollectionUtils.isNotEmpty(steps)) {
            getTaskStepDao().deleteInTx(steps);
        }

        // 清空备注信息
        ServiceFactory.getInstance().getRemarkService().clearRemark(AppStatus.RemarkType.TASK, id);

        getTaskDao().deleteByKey(id);
    }

    public void delTaskStep(Long id) {
        TaskStep t = getTaskStepDao().load(id);
        if (t == null) {
            return;
        }
        getTaskStepDao().deleteByKey(id);
    }


    public TaskItemVo getTaskItemVo(Long id) {
        if (id == 0) {
            return null;
        }
        return convertTask(load(id));
    }

    public TaskStep getTaskStep(Long id) {
        if (id == 0) {
            return null;
        }
        return getTaskStepDao().load(id);
    }

    public List<TaskStep> findTaskStep(Long id) {
        if (id == 0) {
            return new ArrayList<>(0);
        }
        return getTaskStepDao().queryBuilder().where(TaskStepDao.Properties.TaskId.eq(id)).list();
    }


    private TaskItemVo convertTask(Task task) {

        int finish = 0;

        List<TaskStep> steps = findTaskStep(task.getId());
        for (TaskStep s : steps) {
            if (s.getIsFinish()) {
                finish++;
            }
        }

        TaskItemVo v = new TaskItemVo();
        v.setId(task.getId());
        v.setLabTitle(task.getTitle());

        v.setStale(false);
        if (task.getDeadline() != null) {
            if (DateUtils.sameDate(task.getDeadline(), new Date())) {
                v.setLabDate("今天");
            } else if (DateUtils.sameDate(task.getDeadline(), DateUtils.moveDay(1))) {
                v.setLabDate("明天");
            } else {
                v.setLabDate(DateUtils.date2str(task.getDeadline(), DateUtils.F31));

                if (DateUtils.compareDate(task.getDeadline(), new Date()) < 0) {
                    v.setStale(true);
                }
            }
        }

        v.setLabBranch(finish + "/" + steps.size());
        v.setLabMinute(task.getPreMinute() + "分钟");

        v.setShowBranch(steps.size() > 0);
        v.setShowMinute(task.getPreMinute() > 0);
        v.setShowRepet(task.getRepeatType() != AppStatus.RepeatType.ONETIME);
        //task.getRemindType() == AppStatus.RemindType.NORMAL
        v.setShowStar(task.getIsStar());
        v.setShowStudy(task.getTaskType().equals(AppStatus.TaskType.STUDY));
        v.setShowFinish(task.getIsFinish());

        v.setQuadrant(task.getQuadrant());
        v.setTaskType(task.getTaskType());
        v.setSourceId(task.getSourceId());
        return v;
    }

    public Task getDefaultTaskData() {
        Task t = new Task();
        t.setTitle("这是自动生成的任务数据");
        t.setSite("");
        t.setTaskType(AppStatus.TaskType.NORMAL);
        t.setSourceId(0L);
        t.setRepeatType(AppStatus.RepeatType.ONETIME);
        t.setRemindType(AppStatus.RemindType.NORMAL);
        t.setPreMinute(25); // 番茄时间
        t.setIsFinish(false);
        t.setIsPastDue(false);
        t.setIsStar(false);
        t.setRepeatCron("");
        t.setQuadrant(AppStatus.Quadrant.FOUR);
        t.setFinishDt(null);
        t.setStartDt(new Date());
        // 默认截止日期为今天
        t.setDeadline(DateUtils.setEndTime());
        t.setCreatedDt(new Date());
        t.setUpdatedDt(t.getCreatedDt());
        t.setStatus(AppStatus.Status.NORMAL);
        t.setSort(1);
        return t;
    }

    public TaskStep getDefaultTaskStepData(@NonNull Long taskId) {
        TaskStep t = new TaskStep();
        t.setTaskId(taskId);
        t.setTitle("任务" + taskId + "的步骤信息");
        t.setIsFinish(false);
        t.setCreatedDt(new Date());
        t.setUpdatedDt(t.getCreatedDt());
        t.setSort(1);
        return t;
    }

    public Task load(Long id) {
        getTaskDao().detachAll();
        if (id == 0) {
            return null;
        }
        return getTaskDao().load(id);
    }

    public void doFinish(Long taskId, boolean isFinish) {
        // 任务完成
        doFinish(taskId, isFinish, new Date());
    }

    public void doFinish(Long taskId, boolean isFinish, Date finishDt) {
        if (taskId == null) {
            return;
        }

        Task t = load(taskId);
        if (t != null && t.getIsFinish() != isFinish) {

            t.setIsFinish(isFinish);
            t.setFinishDt(isFinish ? finishDt : null);
            t.setUpdatedDt(new Date());

            // 完成时间超过截止日期标记逾期状态
            if (isFinish && DateUtils.compareDate(t.getDeadline(), t.getFinishDt()) < 0) {
                t.setIsPastDue(true);
            }

            getTaskDao().save(t);

            // 继承产生的任务需要同步状态
            if (t.getSourceId() > 0 && t.getSourceId() != null) {
                if (t.getTaskType() == AppStatus.TaskType.GOAL || t.getTaskType() == AppStatus.TaskType.STUDY) {
                    Event e = getEventDao().load(t.getSourceId());
                    if (e == null) {
                        return;
                    }
                    e.setFinish(t.getIsFinish());
                    e.setFinishDt(t.getFinishDt());
                    e.setUpdatedDt(t.getUpdatedDt());
                    getEventDao().save(e);

                    if (t.getTaskType() == AppStatus.TaskType.STUDY) {
                        // 自动续学
                        ServiceFactory.getInstance().getCurriculumService().doAudoContinue(e);
                    }
                }
            }
        }
    }

    public void doStar(Long id, boolean b) {
        if (id == null) {
            return;
        }

        Task t = load(id);
        if (t != null && t.getIsStar() != b) {
            t.setIsStar(b);
            t.setUpdatedDt(new Date());
            getTaskDao().save(t);
        }
    }

    public void saveTaskTitle(Long id, String val) {
        if (id == null || TextUtils.isEmpty(val)) {
            return;
        }

        Task t = load(id);
        if (t != null && !TextUtils.isEmpty(val) && !t.getTitle().equals(val)) {
            t.setTitle(val);
            t.setUpdatedDt(new Date());
            getTaskDao().save(t);
            getTaskDao().detachAll();
        }
    }

    public void saveTaskPreMinute(Long id, int val) {
        if (id == null) {
            return;
        }

        Task t = load(id);
        if (t != null && t.getPreMinute() != val) {
            t.setPreMinute(val);
            t.setUpdatedDt(new Date());
            getTaskDao().save(t);
            getTaskDao().detachAll();

            // 继承产生的任务需要同步状态
            if (t.getSourceId() > 0 && t.getSourceId() != null) {
                if (t.getTaskType() == AppStatus.TaskType.GOAL || t.getTaskType() == AppStatus.TaskType.STUDY) {
                    Event e = getEventDao().load(t.getSourceId());
                    if (e == null) {
                        return;
                    }

                    e.setPreMinute(val);
                    e.setUpdatedDt(t.getUpdatedDt());
                    getEventDao().save(e);
                    getEventDao().detachAll();
                }
            }
        }
    }

    public void saveQuadrant(Long id, Integer quadrant) {
        if (id == null) {
            return;
        }

        Task t = load(id);
        if (t != null && !t.getQuadrant().equals(quadrant)) {
            t.setQuadrant(quadrant);
            t.setUpdatedDt(new Date());
            getTaskDao().save(t);
            getTaskDao().detachAll();
        }
    }

    public void saveTaskDeadline(Long id, Date dt) {
        if (id == null) {
            return;
        }

        Task t = load(id);
        if (t != null) {
            System.out.println(">>>>同一天吗?" + DateUtils.sameDate(t.getDeadline(), dt));
        }
        if (t != null && !DateUtils.sameDate(t.getDeadline(), dt)) {
            t.setDeadline(dt);
            t.setUpdatedDt(new Date());
            getTaskDao().save(t);
            getTaskDao().detachAll();
        }
    }

    public void saveTaskRemind(Long id, Date dt) {
        if (id == null) {
            return;
        }

        Task source = load(id);
        if (source == null) {
            return;
        }
        source.setRemindDt(dt);
        source.setUpdatedDt(new Date());
        getTaskDao().save(source);
        getTaskDao().detachAll();
    }

    public void doStepFinish(Long id, boolean b) {
        TaskStep t = getTaskStepDao().load(id);
        if (t == null || t.getIsFinish() == b) {
            return;
        }
        t.setIsFinish(b);
        t.setUpdatedDt(new Date());
        getTaskStepDao().save(t);
    }

    public void saveTaskStepTitle(Long id, String val) {
        TaskStep t = getTaskStepDao().load(id);
        if (t == null || TextUtils.isEmpty(val) || t.getTitle().equals(val)) {
            return;
        }
        t.setTitle(val);
        t.setUpdatedDt(new Date());
        getTaskStepDao().save(t);
    }


    public static class UpdateDtAscComparetor implements Comparator<Task> {
        @Override
        public int compare(Task lhs, Task rhs) {
            long lTime = lhs.getUpdatedDt().getTime();
            long rTime = rhs.getUpdatedDt().getTime();
            if (lTime > rTime) {
                return 1;
            } else if (lTime < rTime) {
                return -1;
            } else {
                return 0;
            }
        }
    }

    public static class UpdateDtDescComparetor implements Comparator<Task> {
        @Override
        public int compare(Task lhs, Task rhs) {
            long lTime = lhs.getUpdatedDt().getTime();
            long rTime = rhs.getUpdatedDt().getTime();
            if (lTime > rTime) {
                return -1;
            } else if (lTime < rTime) {
                return 1;
            } else {
                return 0;
            }
        }
    }

    public static class CreateDtAscComparetor implements Comparator<Task> {
        @Override
        public int compare(Task lhs, Task rhs) {
            long lTime = lhs.getCreatedDt().getTime();
            long rTime = rhs.getCreatedDt().getTime();
            if (lTime > rTime) {
                return 1;
            } else if (lTime < rTime) {
                return -1;
            } else {
                return 0;
            }
        }
    }

    public static class CreateDtDescComparetor implements Comparator<Task> {
        @Override
        public int compare(Task lhs, Task rhs) {
            long lTime = lhs.getCreatedDt().getTime();
            long rTime = rhs.getCreatedDt().getTime();
            if (lTime > rTime) {
                return -1;
            } else if (lTime < rTime) {
                return 1;
            } else {
                return 0;
            }
        }
    }

    public static class DeadlineAscComparetor implements Comparator<Task> {
        @Override
        public int compare(Task lhs, Task rhs) {
            long lTime = lhs.getDeadline().getTime();
            long rTime = rhs.getDeadline().getTime();
            if (lTime > rTime) {
                return 1;
            } else if (lTime < rTime) {
                return -1;
            } else {
                return 0;
            }
        }
    }

    public static class DeadlineDescComparetor implements Comparator<Task> {
        @Override
        public int compare(Task lhs, Task rhs) {
            long lTime = lhs.getDeadline().getTime();
            long rTime = rhs.getDeadline().getTime();
            if (lTime > rTime) {
                return -1;
            } else if (lTime < rTime) {
                return 1;
            } else {
                return 0;
            }
        }
    }

    public static class TitleDescComparetor implements Comparator<Task> {
        @Override
        public int compare(Task lhs, Task rhs) {
            String lTitle = lhs.getTitle();
            String rTitle = rhs.getTitle();
            return lTitle.compareTo(rTitle);
        }
    }

    public static class TitleAscComparetor implements Comparator<Task> {
        @Override
        public int compare(Task lhs, Task rhs) {
            String lTitle = lhs.getTitle();
            String rTitle = rhs.getTitle();
            return rTitle.compareTo(lTitle);
        }
    }

    public static class IDAscComparetor implements Comparator<Task> {
        @Override
        public int compare(Task lhs, Task rhs) {
            long lid = lhs.getId();
            long rid = rhs.getId();
            if (lid > rid) {
                return 1;
            } else if (lid < rid) {
                return -1;
            } else {
                return 0;
            }
        }
    }

    public static class IDDescComparetor implements Comparator<Task> {
        @Override
        public int compare(Task lhs, Task rhs) {
            long lid = lhs.getId();
            long rid = rhs.getId();
            if (lid > rid) {
                return -1;
            } else if (lid < rid) {
                return 1;
            } else {
                return 0;
            }
        }
    }

    public static class StarAscComparetor implements Comparator<Task> {
        @Override
        public int compare(Task lhs, Task rhs) {
            int lid = lhs.getIsStar() ? 1 : 0;
            int rid = rhs.getIsStar() ? 1 : 0;
            if (lid > rid) {
                return 1;
            } else if (lid < rid) {
                return -1;
            } else {
                return 0;
            }
        }
    }

    public static class StarDescComparetor implements Comparator<Task> {
        @Override
        public int compare(Task lhs, Task rhs) {
            int lid = lhs.getIsStar() ? 1 : 0;
            int rid = rhs.getIsStar() ? 1 : 0;
            if (lid > rid) {
                return -1;
            } else if (lid < rid) {
                return 1;
            } else {
                return 0;
            }
        }
    }

    public static class QuadrantAscComparetor implements Comparator<Task> {
        @Override
        public int compare(Task lhs, Task rhs) {
            if (lhs.getQuadrant() > rhs.getQuadrant()) {
                return 1;
            } else if (lhs.getQuadrant() < rhs.getQuadrant()) {
                return -1;
            } else {
                return 0;
            }
        }
    }

    public static class QuadrantDescComparetor implements Comparator<Task> {
        @Override
        public int compare(Task lhs, Task rhs) {
            if (lhs.getQuadrant() > rhs.getQuadrant()) {
                return -1;
            } else if (lhs.getQuadrant() < rhs.getQuadrant()) {
                return 1;
            } else {
                return 0;
            }
        }
    }

    public static class FinishAscComparetor implements Comparator<Task> {
        @Override
        public int compare(Task lhs, Task rhs) {
            int lid = lhs.getIsFinish() ? 1 : 0;
            int rid = rhs.getIsFinish() ? 1 : 0;
            if (lid > rid) {
                return 1;
            } else if (lid < rid) {
                return -1;
            } else {
                return 0;
            }
        }
    }

    public static class FinishDescComparetor implements Comparator<Task> {
        @Override
        public int compare(Task lhs, Task rhs) {
            int lid = lhs.getIsFinish() ? 1 : 0;
            int rid = rhs.getIsFinish() ? 1 : 0;
            if (lid > rid) {
                return -1;
            } else if (lid < rid) {
                return 1;
            } else {
                return 0;
            }
        }
    }

    public KeyValueVo getTaskSource(Long taskId) {
        Task t = load(taskId);
        if (t != null) {
            Event e = getEventDao().load(t.getSourceId());// 事件源
            if (e != null) {
                if (t.getTaskType() == AppStatus.TaskType.GOAL) {
                    Goals g = getGoalsDao().load(e.getSourceId());
                    if (g != null) {
                        return new KeyValueVo(g.getId(), g.getTitle());
                    }
                } else if (t.getTaskType() == AppStatus.TaskType.STUDY) {
                    Curriculum c = getCurriculumDao().load(e.getSourceId());
                    if (c != null) {
                        return new KeyValueVo(c.getId(), c.getTitle());
                    }
                }
            }
        }
        return null;
    }

    public void dispostData() {
        /*for (Habit t : getHabitDao().loadAll()) {
            t.setQuadrant(AppStatus.Quadrant.FOUR);
            getHabitDao().save(t);
        }*/
    }

}
